package me.yricky.hid.desktop.mainnav

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
import me.yricky.hid.desktop.AppState
import me.yricky.hid.desktop.IconButton
import me.yricky.hid.desktop.Theme
import me.yricky.hid.desktop.device.DeviceState
import me.yricky.usbhid.HidDevice
import java.lang.Integer.max
import java.lang.Integer.min
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter

class MainNavDebugTabs(private val appState: AppState): MainNav() {
    val openedDevices = mutableStateListOf<DeviceState>()
    private val tabState = LazyListState()
    private var currIndex by mutableStateOf(0)

    fun openTab(device:HidDevice){
        openedDevices.findLast { it.device.path == device.path }?.refresh(device) ?: openedDevices.add(DeviceState(device))
        currIndex = (openedDevices.indexOfLast { it.device.path == device.path })
    }

    fun closeTab(index:Int){
        openedDevices.getOrNull(index)?.let {
            it.device.close()
            openedDevices.remove(it)
            currIndex = index.coerceAtMost(openedDevices.size - 1)
        }
    }

    @Composable
    override fun Content(modifier: Modifier) {
        val scope = rememberCoroutineScope()
        LaunchedEffect(currIndex){
            scope.launch {
                if(currIndex>=0){
                    tabState.animateScrollToItem(currIndex)
                }else{
                    appState.mainNav = appState.mainNavDeviceList
                }
            }
        }
        Column(Modifier.fillMaxSize()) {
            LazyRow(
                Modifier.fillMaxWidth().height(32.dp),
                state = tabState
            ) {
                itemsIndexed(openedDevices){ index,it ->
                    val bgColor = MaterialTheme.colors.primary
                    Box(
                        Modifier.drawBehind {
                            if(currIndex == index){
                                drawRect(bgColor, Offset(0f,size.height * 0.95f))
                            }
                        }
                    ) {
                        Row(
                            Modifier.fillMaxHeight()
                                .widthIn(0.dp,320.dp)
                                .clickable { currIndex = index },
                            verticalAlignment = Alignment.CenterVertically,
                        ) {
                            IconButton(24.dp,
                                when(it.device.busType){
                                    HidDevice.USB -> Theme.Icons.usb()
                                    HidDevice.BLUETOOTH -> Theme.Icons.bluetooth()
                                    HidDevice.I2C -> Theme.Icons.i2c()
                                    HidDevice.SPI -> Theme.Icons.spi()
                                    else -> Theme.Icons.unknown()
                                }){}
                            Text(
                                "${it.device.productName} ${it.device.path}".trim(),
                                maxLines = 1,
                                overflow = TextOverflow.Clip,
                                modifier = Modifier.padding(end = 24.dp),
                                softWrap = false
                            )
                        }
                        Box(Modifier.align(Alignment.CenterEnd)){
                            IconButton(
                                24.dp,
                                painter = Theme.Icons.close(),
                            ){
                                closeTab(index)
                            }
                        }
                    }

                }
            }
            Box(Modifier.fillMaxWidth().weight(1f)){
                val currDevice = openedDevices.getOrNull(currIndex)
                val listState = rememberLazyListState()
                currDevice?.let {dev ->
                    Column {
                        Row(Modifier.padding(8.dp,0.dp)) {
                            IconButton(
                                24.dp,
                                Theme.Icons.alignBottom(),
                                MaterialTheme.colors.primary.takeIf { dev.lockLast }
                            ){ dev.lockLast = !dev.lockLast }
                            IconButton(
                                24.dp,
                                Theme.Icons.clock(),
                                MaterialTheme.colors.primary.takeIf { dev.showTime }
                            ){ dev.showTime = !dev.showTime }
                            IconButton(
                                24.dp,
                                Theme.Icons.delete(),
                                MaterialTheme.colors.primary.takeIf { dev.dataHistory.isNotEmpty() }
                            ){ dev.clearHistory() }
                        }
                        Box(
                            Modifier.padding(8.dp,0.dp).background(MaterialTheme.colors.surface, RoundedCornerShape(4.dp))
                                .padding(4.dp).weight(1f).fillMaxWidth()
                        ) {

                            LazyColumn(
                                state = listState
                            ) {
                                items(dev.dataHistory){
                                    Row(
                                        Modifier.fillMaxWidth(),
                                    ) {
                                        IconButton(16.dp,
                                            if(it.isSend){
                                                Theme.Icons.send()
                                            }else{
                                                Theme.Icons.receive()
                                            }
                                        ){}
                                        val time = LocalDateTime.ofInstant(
                                            Instant.ofEpochMilli(it.repeatTimes.lastOrNull() ?: it.timestamp),
                                            ZoneId.systemDefault()
                                        ).format(DateTimeFormatter.ofPattern("HH:mm:ss:SSS"))
                                            .let { "[$it] " }
                                            .takeIf { dev.showTime } ?: ""
                                        val dataStr = it.data.takeIf { it.isNotEmpty() }
                                            ?.map { String.format("%02X",it) }
                                            ?.reduceRight { s1, s2 -> "$s1 $s2" } ?: ""
                                        val repeat = it.repeatTimes.size.takeIf { it > 0 }
                                            ?.let { " (${it + 1}${if(it >= dev.historySize) "+" else ""})" } ?:""
                                        Text(
                                            "$time$dataStr$repeat",
//                                            maxLines = 1,
                                            overflow = TextOverflow.Ellipsis,
                                            fontFamily = FontFamily.Monospace
                                        )
                                    }
                                }
                                item {
                                    Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically){
                                        val text = if(dev.remainedReadTimes == 0){
                                            "停止读取"
                                        }else if(dev.remainedReadTimes < 0){
                                            "一直读取"
                                        }else{
                                            "还会读取${dev.remainedReadTimes}次"
                                        }
                                        if(dev.isBlockReading){
                                            Box {
                                                CircularProgressIndicator(Modifier.size(20.dp), strokeWidth = 2.dp)
                                                IconButton(20.dp, Theme.Icons.receive()){}
                                            }
                                        }
                                        if(dev.isBlockWriting){
                                            Box {
                                                CircularProgressIndicator(Modifier.size(20.dp), strokeWidth = 2.dp)
                                                IconButton(20.dp, Theme.Icons.send()){}
                                            }
                                        }
                                        Text("- 到底啦，$text -")
                                    }
                                }
                            }
                            VerticalScrollbar(adapter = ScrollbarAdapter(listState),Modifier.align(Alignment.CenterEnd))
                        }
                        LaunchedEffect(dev.totalActionCount,dev.lockLast){
                            launch {
                                if(dev.lockLast && listState.layoutInfo.totalItemsCount > 0){
                                    listState.scrollToItem(dev.dataHistory.size)
                                }
                            }
                        }
                        Row(
                            modifier = Modifier.padding(8.dp,4.dp),
                        ) {
                            Surface(
                                shape = RoundedCornerShape(64.dp),
                                color = MaterialTheme.colors.background,
                                border = BorderStroke(1.dp,MaterialTheme.colors.primary)
                            ) {
                                Row(
                                    modifier = Modifier.padding(2.dp),
                                    verticalAlignment = Alignment.CenterVertically,
                                ) {
                                    var times by remember {
                                        mutableStateOf(500)
                                    }
                                    IconButton(
                                        20.dp,Theme.Icons.receive(),
                                        tint = MaterialTheme.colors.primary.takeIf { dev.remainedReadTimes == 0 }
                                    ){
                                        if(dev.remainedReadTimes == 0){
                                            dev.setReadTimes(times)
                                        }else{
                                            dev.setReadTimes(0)
                                        }
                                    }
                                    BasicTextField(
                                        "$times",
                                        { times = it.toIntOrNull()?.coerceIn(-1,9999) ?: 0 },
                                        Modifier.width(80.dp),
                                        textStyle = TextStyle(color = MaterialTheme.colors.onBackground),
                                        cursorBrush = SolidColor(MaterialTheme.colors.primary)
                                    )
                                }
                            }

                        }
                        var expand by remember {
                            mutableStateOf(false)
                        }
                        var sendContent by remember {
                            mutableStateOf(ByteArray(0))
                        }
                        OutlinedTextField(
                            value = sendContent.takeIf { it.isNotEmpty() }
                                ?.map { String.format("%02X",it) }
                                ?.reduce{ b1,b2 -> "$b1 $b2" }?.let { " $it " } ?: "",
                            onValueChange = {sendContent = it.split(" ")
                                .filter { it.isNotBlank() }
                                .mapNotNull { it.substring(max(0,it.length - 2),it.length).uppercase().toUByteOrNull(16)?.toByte() }.toByteArray() },
                            textStyle = TextStyle(fontFamily = FontFamily.Monospace),
                            modifier = Modifier
                                .fillMaxWidth()
                                .wrapContentHeight()
                                .padding(start = 8.dp,end = 8.dp, bottom = 8.dp)
                                .let { if (expand) it.weight(3f) else it },
                            trailingIcon = {
                                if(expand){
                                    Column(Modifier.padding(4.dp,4.dp)) {
                                        IconButton(28.dp,Theme.Icons.shrink()){ expand = !expand }
                                        Spacer(Modifier.weight(1f))
                                        IconButton(28.dp,Theme.Icons.sendAction()){ expand = false }
                                    }
                                }else{
                                    Row(Modifier.padding(4.dp,4.dp)) {
                                        IconButton(28.dp,Theme.Icons.expand()){ expand = !expand }
                                        IconButton(28.dp,Theme.Icons.sendAction()){
                                            dev.postWrite(sendContent)
                                        }
                                    }
                                }
                            },
                            maxLines = if(expand) Int.MAX_VALUE else 1
                        )
                    }
                }
            }
        }
    }
}